'''
Contains emulation components for asyncore library.

@author: Hatem Oraby
'''

from twistedSim.overrideManager import OverrideManager

firstRun = True
_timeout = None
_map = None
_use_poll = None
_count = None
_poll_fun = None

class wrapper:
    '''
    Wrapper around asyncore function. It is more a stateful tracking of
    asyncore function and all its data in a single object.
    '''
    def __init__(self,  timeout=30.0, use_poll=False, map=None, count=None):
        self.firstRun = True
        self._timeout = None
        self._map = None
        self._use_poll = None
        self._count = None
        self._poll_fun = None

    
    def loop(self):
        import select
        import asyncore
        self._map = asyncore.socket_map
        self._poll_fun = asyncore.poll
        poll_fun = self._poll_fun
        from twistedSim.simManager import Module
        currentModule = Module.getCurrentModule()
        
        keepLooping = True
        while keepLooping:
            if self._count is None:
                if self._map:
                    #poll_fun(timeout, map)
                    self._poll_fun(0, self._map)
            else:
                if self._map and self._count > 0:
                    self._poll_fun(0, self._map)
                    self._count = self._count - 1
    
            keepLooping = False
            if self._map:
                for fd, obj in self._map.items():
                    r, w, e = select.select([fd], [fd], [fd], 0)
                    if r or w or e:
                        keepLooping = True
                        break #Break from the for-loop
                #for-loop ends here
        #while-loop ends here
    #Method ends here
                    

def loop(timeout=30.0, use_poll=False, map=None, count=None):
    '''Ovverides asyncore.loop with this loop '''
    global firstRun, _timeout, _map, _use_poll, _count, _poll_fun
    import select
    if firstRun:
        if map is None:
            import asyncore
            map = asyncore.socket_map
        #I'm forcing the use of select
        _poll_fun = asyncore.poll
        firstRun = False
        _timeout = timeout
        _use_poll = use_poll
        _map = map
        _count = count
        
    poll_fun = _poll_fun
    from twistedSim.simManager import Module
    currentModule = Module.getCurrentModule()

    keepLooping = True
    while keepLooping:
        if count is None:
            if map:
                #poll_fun(timeout, map)
                poll_fun(0, map)
        else:
            if map and count > 0:
                poll_fun(0, map)
                count = count - 1

        keepLooping = False
        if map:
            for fd, obj in map.items():
                r, w, e = select.select([fd], [fd], [fd], 0)
                if r or w or e:
                    keepLooping = True
                    break #Break from the for-loop
            #for-loop ends here
    #while-loop ends here
#Function ends here
            
def install():
    import asyncore
    OverrideManager.storeEntity(asyncore.loop, "asyncore.loop")
    
    asyncore.loop = loop
    
def uninstall():
    originalLoop = OverrideManager.getEntity("asyncore.loop")
    import asyncore
    asyncore.loop = originalLoop